/*
 *  $Id: Particle.cs 1190 2010-11-12 15:02:56Z thenn.erannor $
 *  This file is a part of Ragima CCG.
 *  (C) 2008-2009 Ragima development group.
 *
 *  Licensed under the terms of the GNU GPL License version 2.
 *
 */

using System.Collections.Generic;

using AgateLib.DisplayLib;
using AgateLib.Geometry;

using Ragima.Helper;

namespace Ragima.UI {
    /// <summary>
    /// Отдельная частица.
    /// </summary>
    public class Particle {
        private Surface _image;
        private ParticleState[] _phases;
        private int _phase;
        private ParticleState _state;
        private IEnumerator<PointF> _trajectory;
        private PointF _center, _offset;

        public Particle(ParticleInfo info, Point center) {
            _image = info.Image;
            _phases = new ParticleState[info.Phases.Count];
            for (int i = 0; i < _phases.Length; i++) {
                _phases[i] = info.Phases[i].Clone();
            }
            _center = center.ToF();
            _offset = PointF.Empty;
            _phase = 0;
            _state = CurrentPhase.Clone();
            _state.MorphTime = 0;
            _trajectory = null;
            UpdateTrajectory();
            UpdateOffset();
        }

        public bool Ended {
            get { return _phase >= _phases.Length; }
        }

        public PointF Center {
            get { return _center; }
        }

        public PointF Position {
            get { return _center.Add(_offset); }
        }

        private ParticleState CurrentPhase {
            get { return _phases[_phase]; }
        }

        private ParticleState PreviousPhase {
            get { return _phases[_phase > 0 ? _phase - 1 : 0]; }
        }

        public void Draw() {
            if (Ended)
                return;
            SetImageState();
            _image.Draw(Position);
        }

        public void Process() {
            if (Ended)
                return;

            // изменение состояния
            if (_state.MorphTime > 0) {
                ChangeState();
                _state.MorphTime--;
            } else {
                if (_state.LifeTime > 0) {
                    _state.LifeTime--;
                } else {
                    ChangePhase();
                }
            }

            // изменение положения
            UpdateOffset();
        }

        public void MoveBy(PointF offset) {
            _center.X += offset.X;
            _center.Y += offset.Y;
        }

        private void ChangePhase() {
            _phase++;
            if (!Ended) {
                _state.MorphTime = CurrentPhase.MorphTime;
                _state.LifeTime = CurrentPhase.LifeTime;
                UpdateTrajectory();
            }
        }

        private void ChangeState() {
            ParticleState start = PreviousPhase, end = CurrentPhase;
            double step = (double) (end.MorphTime - _state.MorphTime) / end.MorphTime;
            _state.Change(start, end, step);
        }

        private void UpdateTrajectory() {
            if (CurrentPhase.Trajectory != null) {
                if (_trajectory != null)
                    _trajectory.Dispose();
                _center = Position;
                _offset = PointF.Empty;
                _trajectory = CurrentPhase.Trajectory.GetEnumerator();
            }
        }

        private void UpdateOffset() {
            if (_trajectory == null)
                return;
            if (_trajectory.MoveNext()) {
                _offset = _trajectory.Current;
            } else {
                _trajectory.Dispose();
                _trajectory = null;
            }
        }

        public void SetImageState() {
            _image.Color = _state.Color;
            _image.Alpha = _state.Alpha;
            _image.SetScale(_state.Scale, _state.Scale);
            _image.RotationAngleDegrees = _state.Angle;
        }
    }
}
